package com.itfreer.arcgis.utils;

import com.esri.arcgisruntime.concurrent.ListenableFuture;
import com.esri.arcgisruntime.data.Feature;
import com.esri.arcgisruntime.data.FeatureQueryResult;
import com.esri.arcgisruntime.data.FeatureTable;
import com.esri.arcgisruntime.data.Field;
import com.esri.arcgisruntime.data.QueryParameters;
import com.esri.arcgisruntime.data.ShapefileFeatureTable;
import com.esri.arcgisruntime.geometry.Geometry;
import com.esri.arcgisruntime.geometry.GeometryType;
import com.esri.arcgisruntime.geometry.Polygon;
import com.esri.arcgisruntime.geometry.Polyline;
import com.itfreer.arcgis.query.QueryListener;
import com.itfreer.utils.common.LogUtils;
import com.itfreer.utils.common.StringUtils;
import com.itfreer.utils.common.ToastUtils;
import com.itfreer.utils.config.ConfigManager;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;

/**
 * 矢量数据表对象
 */
public class FeatureTableUtils {
    /***
     * 属性查询
     *
     * @param featureTable
     *            查询图层
     * @param params
     *            查询条件
     */
    public static void AttributeQuery(final FeatureTable featureTable, String params, final QueryListener listener) {
        Query(featureTable, params, null, listener);
    }

    /***
     * 属性查询
     *
     * @param featureTable
     *            查询图层
     * @param params
     *            查询条件
     */
    public static void Query(final FeatureTable featureTable, String params, Geometry geometry,
                             final QueryListener listener) {
        QueryParameters queryParams = new QueryParameters();
        if (StringUtils.IsNullOrEmpty(params))
            params = "1=1";
        queryParams.setWhereClause(params);
        if (geometry != null && !geometry.isEmpty())
            queryParams.setGeometry(geometry);
        queryParams.setSpatialRelationship(QueryParameters.SpatialRelationship.INTERSECTS);
        final ListenableFuture<FeatureQueryResult> future = featureTable.queryFeaturesAsync(queryParams);
        future.addDoneListener(new Runnable() {
            @Override
            public void run() {
                try {
                    // 获取查询结果
                    FeatureQueryResult result = future.get();

                    List<Feature> features = new ArrayList<Feature>();
                    Iterator<Feature> iterator = result.iterator();
                    Feature feature;
                    while (iterator.hasNext()) {
                        feature = iterator.next();
                        features.add(feature);
                    }
                    if (listener != null)
                        listener.execute(featureTable, features);
                } catch (InterruptedException | ExecutionException e) {
                    LogUtils.Print("Error in FeatureQueryResult: " + e.getMessage(), LogUtils.Lever.Error);
                    ToastUtils.showLong(ConfigManager.getContext(), "SQL异常！");
                }
            }
        });
    }

    /**
     * 打开本地的shape文件转成FeatureTable
     *
     * @param path
     * @return
     */
    public static FeatureTable GetFeatureTableFormShape(String path) {
        try {
            ShapefileFeatureTable shapefileFeatureTable = new ShapefileFeatureTable(path);
            return shapefileFeatureTable;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 判断是否为系统字段
     *
     * @param featureTable
     *            矢量图层对象
     * @param fieldName
     *            字段名
     * @return
     */
    public static Boolean IsSystemField(FeatureTable featureTable, String fieldName) {
        if (StringUtils.IsNullOrEmpty(fieldName))
            return false;
        Field field = featureTable.getField(fieldName);
        if (field == null)
            return null;

        if (field.getFieldType().equals(Field.Type.OID))
            return true;

        if (field.getFieldType().equals(Field.Type.GEOMETRY))
            return true;

        if (field.getFieldType().equals(Field.Type.GLOBALID))
            return true;

        if (field.getFieldType().equals(Field.Type.GUID))
            return true;

        if (field.getFieldType().equals(Field.Type.BLOB))
            return true;

        if (field.getFieldType().equals(Field.Type.RASTER))
            return true;

        if (fieldName.toUpperCase().equals("SHAPE_LENGTH"))
            return true;

        if (fieldName.toUpperCase().equals("SHAPE_AREA"))
            return true;

        return false;
    }

    /**
     * 根据字段名判断字段是否存在
     * @param fileName
     * @return
     */
    public static Boolean IsFieldExist(FeatureTable featureTable, String fileName)
    {
        if(featureTable == null || StringUtils.IsNullOrEmpty(fileName))
            return  false;

        for(Integer i =0 ;i<featureTable.getFields().size();i++)
        {
            if(featureTable.getFields().get(i).getName().equals(fileName))
            {
                return  true;
            }
        }
        return  false;
    }
    /**
     * 获取OID字段名
     *
     * @param featureTable
     *            矢量图层对象
     * @return
     */
    public static String GetOIDFieldName(FeatureTable featureTable) {
        Field field = GetOIDField(featureTable);
        if (field == null)
            return "";
        else
            return field.getName();
    }

    /**
     * 获取OID字段名
     *
     * @param featureTable
     *            矢量图层对象
     * @return
     */
    public static Field GetOIDField(FeatureTable featureTable) {
        if (featureTable == null)
            return null;

        for (Integer i = 0; i < featureTable.getFields().size(); i++) {
            if (featureTable.getFields().get(i).getFieldType().equals(Field.Type.OID))
                return featureTable.getFields().get(i);
        }
        return null;
    }

    /**
     * 是否是点要素
     *
     * @param featureTable
     * @return
     */
    public static boolean isPointFeatuerTable(FeatureTable featureTable) {
        return featureTable.getGeometryType() == GeometryType.POINT
                || featureTable.getGeometryType() == GeometryType.MULTIPOINT;
    }

    /**
     * 是否是线要素
     *
     * @param featureTable
     * @return
     */
    public static boolean isPolylineFeatuerTable(FeatureTable featureTable) {
        // TODO 空的要素不知道为啥类型返回UNKNOWN
        Object ssss = featureTable.getLoadStatus();
        return featureTable.getGeometryType() == GeometryType.POLYLINE;
    }

    /**
     * 是否是面要素
     *
     * @param featureTable
     * @return
     */
    public static boolean isPolygonFeatuerTable(FeatureTable featureTable) {
        return featureTable.getGeometryType() == GeometryType.POLYGON
                || featureTable.getGeometryType() == GeometryType.ENVELOPE;
    }

    /**
     * 依据字段名称获取得到标注对象
     *
     * @param featureTable
     *            矢量图层对象
     * @return
     */
    public static Field GetLabelField(FeatureTable featureTable, String labelName) {
        if (featureTable == null)
            return null;

        for (Integer i = 0; i < featureTable.getFields().size(); i++) {
            if (featureTable.getFields().get(i).getName().equals(labelName))
                return featureTable.getFields().get(i);
        }
        return null;
    }

    /**
     * 创建元素
     *
     * @param geometry
     *            图形对象
     * @param attributes
     *            属性集合
     * @param featureTable
     *            要素表
     */
    public static Feature AddFeature(Geometry geometry, Map<String, Object> attributes, FeatureTable featureTable) {
        if (geometry == null || geometry.isEmpty()){
            return null;
        }
        if (featureTable == null || !featureTable.canAdd()){
            return null;
        }

        if (geometry.getGeometryType() == GeometryType.POLYGON) {
            Polygon polygon = (Polygon) geometry;
            if (polygon.getParts().size() > 1){
                return null;
            }
        } else if (geometry.getGeometryType() == GeometryType.POLYLINE) {
            Polyline polyline = (Polyline) geometry;
            if (polyline.getParts().size() > 1){
                return null;
            }
        }

        Feature feature = featureTable.createFeature();
        // 如果有属性值，则遍历设置属性值
        // TODO song 后续添加属性类型校验，和系统字段如objectid， shape_length等字段过滤
        if (attributes != null && attributes.size() > 0) {
            for (String in : attributes.keySet()) {
                if (feature.getAttributes().containsKey(in)) {
                    Object value = attributes.get(in);
                    feature.getAttributes().put(in, value);
                }
            }
        }

        feature.setGeometry(geometry);
        featureTable.addFeatureAsync(feature);
        return feature;
    }

    /**
     * 创建元素
     *
     * @param feature
     *            要素对象
     * @param featureTable
     *            要素表
     */
    public static void UpdateFeature(FeatureTable featureTable, Feature feature) {
        if (feature == null || feature.getGeometry() == null || feature.getGeometry().isEmpty())
            return;

        // 多部分不允许保存
        if (feature.getGeometry().getGeometryType() == GeometryType.POLYGON) {
            Polygon polygon = (Polygon) feature.getGeometry();
            if (polygon.getParts().size() > 1)
                return;
        } else if (feature.getGeometry().getGeometryType() == GeometryType.POLYLINE) {
            Polyline polyline = (Polyline) feature.getGeometry();
            if (polyline.getParts().size() > 1)
                return;
        }

        if (featureTable == null || !featureTable.canAdd())
            return;

        if (!featureTable.canUpdate(feature))
            return;

        featureTable.updateFeatureAsync(feature);
    }

    /**
     * 删除选择要素
     *
     * @param featureTable
     * @param feature
     */
    public static void DeleteFeature(FeatureTable featureTable, final Feature feature)
    {
        if (featureTable == null || feature == null)
            return;

        if (!featureTable.canDelete(feature))
            return;

        featureTable.deleteFeatureAsync(feature);
    }
}